<?php

namespace App\Api\Controllers;

use App\Api\Requests\AddressRequest;
use App\Api\Requests\OrderRequest;
use App\Api\Resources\CartResource;
use App\Api\Resources\DistrictResource;
use App\Api\Resources\OrderResource;
use App\Api\Resources\ProductResource;
use App\Api\Resources\PushResource;
use App\Models\CartModel;
use App\Models\DistrictModel;
use App\Models\OrderModel;
use App\Models\PatientAddressModel;
use App\Models\PatientModel;
use App\Models\ProductModel;
use App\Models\PushModel;
use EasyWeChat\Work\GroupRobot\Messages\Markdown;
use GuzzleHttp\Client;
use Illuminate\Database\Console\Migrations\ResetCommand;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Str;
use EasyWeChat\Factory;
use PHPUnit\Util\Exception;
use Symfony\Component\Cache\Adapter\RedisAdapter;


class ShopController extends Controller
{

    public function getProductList(Request $request)
    {
        try {
            $patientId = $request->input('patient_id');
            if($patientId == null) throw new Exception('参数错误');

            $patient = PatientModel::with('relation.doctor')->find($patientId);
            $orgCode = $patient->relation->doctor->org_code ?? null;
            if ($orgCode == null) {
                $orgCode = 'A01A02';
                // throw new \Exception('数据异常！');
            }
            Log::channel('wechat_pay')->info("$patientId 机构编号 $orgCode");
            Log::channel('wechat_pay')->debug($patient);
            if ($patient == null) throw new \Exception('数据异常');
            // $orgCode = 'A01A02';
            $products = ProductModel::where('product_status', 1)->where('org_code', $orgCode)->orderBy('product_sort', 'desc')->get();
            return $this->success(ProductResource::collection($products));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getProductListV2(Request $request)
    {
        try {
            $patientId = $request->input('patient_id');
            if($patientId == null) throw new Exception('参数错误');

            $patient = PatientModel::with('relation.doctor')->find($patientId);
            $orgCode = $patient->relation->doctor->org_code ?? null;
            if ($orgCode == null) {
                $orgCode = 'A01A02';
                // throw new \Exception('数据异常！');
            }
            Log::channel('wechat_pay')->info("$patientId 机构编号 $orgCode");
            Log::channel('wechat_pay')->debug($patient);
            if ($patient == null) throw new \Exception('数据异常');

            $hot = ProductModel::where('product_status', 1)->where('org_code', $orgCode)->where('product_is_hot', 1)->orderBy('product_push_time', 'desc')->skip(0)->take(3)->get();

            $data = [];
            $productCategory = ProductModel::PRODUCT_CATEGORY;
            foreach ($productCategory as $key => $category) {
                $products = ProductModel::with('sales')
                    ->where('product_status', 1)
                    ->where('org_code', $orgCode)
                    ->where('product_category', $key)
                    ->orderBy('create_time', 'desc')
                    ->get();
                $data[] = [
                    'category_id' => $key,
                    'category_name' => $category,
                    'products' => ProductResource::collection($products)
                ];
            }

            $result = [
                'hot' => ProductResource::collection($hot),
                'list' => $data
            ];

            return $this->success($result);
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getProductDetail(Request $request)
    {
        try {
            if ($request->input('data_id') === null) throw new \Exception('参数错误');
            $product = ProductModel::with('service')->find($request->input('data_id'));
            if ($product === null) throw new \Exception('数据异常');
            return $this->success(new ProductResource($product));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getPcdDict()
    {
        try {
            $pcdList = DistrictModel::tree(DistrictModel::all()->toArray(), 'district_info_di_id', 'district_info_parent_id');
            return $this->success(DistrictResource::collection($pcdList));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function createOrder(OrderRequest $request)
    {
        try {

            $patientId = $request->input('patient_id');
            $addressId = $request->input('address_id');
            $products = $request->input('products');

            $usePrice = $request->input('use_price', 'product_price');

            // 开启事物
            DB::beginTransaction();
            $patient = PatientModel::with('relation.doctor')->find($patientId);
            $orgCode = $patient->relation->doctor->org_code ?? null;
            if ($orgCode == null) {
                $orgCode = 'A01A02';
                // throw new \Exception('数据异常！');
            }
            if ($patient == null) throw new \Exception('数据异常');

            // 配送到家校验收货地址
            if ($request->input('delivery_type') == 2) {
                $patientAddress = PatientAddressModel::find($addressId);
                if ($patientAddress == null) throw new \Exception('收货地址据异常');
            }

            if (!is_array($products)) throw new \Exception('商品信息异常');

            $productIds = Arr::pluck($products, 'id');
            $productNumber = array_sum(Arr::pluck($products, 'num'));
            $sysProducts = ProductModel::whereIn('data_id', $productIds)->get();

            // TODO 存储订单信息
            $orderData = [
                'data_id' => md5(Str::uuid()),
                'order_info_userid' => $patientId,
                'order_info_title' => implode('、', Arr::pluck($sysProducts, 'product_name')),
                'order_info_no' => date('ymdHis').str_pad(random_int(0, 999999), 6, '0'),
                'order_info_sum' => $this->computePrice('product_price', $sysProducts, $products),
                'order_info_payment' => $this->computePrice($usePrice, $sysProducts, $products),
                'order_info_paystatus' => 0,    // 未支付
                'order_info_orderstatus' => 1,  // 待支付
                'order_info_type' => 0,     // 商城订单
                'order_info_pay_type' => 2, // 微信支付
                'remark' => $request->input('remark'),
                'order_info_delivery_type' => $request->input('delivery_type'),
                'order_info_buy_type' => $request->input('buy_type', 0),
                'org_code' => $orgCode,
                'order_info_product_category' => $sysProducts[0]['product_category']
            ];

            $order = OrderModel::create($orderData);
            if (!$order) throw new \Exception('订单创建失败');

            // 创建订单对应的商品信息
            $productData = [];
            foreach ($products as $item) {
                $productInfo = ProductModel::find($item['id']);
                if ($productInfo === null) continue;
                $productData[] = [
                    'product_id' => $item['id'],
                    'product_name' => $productInfo['product_name'],
                    'product_price' => $productInfo['product_price'] * 100,
                    'product_category' => $productInfo['product_category'],
                    'product_discount_price' => $productInfo['product_discount_price'] * 100,
                    'product_vip_price' => $productInfo['product_vip_price'] * 100,
                    'product_service_id' => $productInfo['product_service_id'],
                    'product_thumb' => $productInfo['product_thumb'],
                    'product_num' => $item['num']
                ];
            }
            if (empty($productData)) throw new \Exception('商品信息异常');

            $product = $order->products()->createMany($productData);
            if (!$product) throw new \Exception('商品信息保存失败');

            // 清空购物车
            $deleteCart = CartModel::whereIn('product_id', $productIds)->get();
            if (!is_null($deleteCart)) {
                CartModel::whereIn('product_id', $productIds)->update(['is_del' => 1]);
            }

            // 创建订单对应的收货地址信息
            if ($request->input('delivery_type') == 2) {
                $address = $order->address()->create([
                    'contact_person' => $patientAddress->contact_person,
                    'contact_phone' => $patientAddress->contact_phone,
                    'contact_address' => $patientAddress->contact_full_address,
                ]);
                if (!$address) throw new \Exception('收货信息保存失败');
            }

            DB::commit();
            return $this->success(['order_id' => $order->data_id]);

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }
    }

    private function computePrice($field, $sysProducts, $products) {
        $price = 0;
        foreach ($sysProducts as $sysProduct) {
            foreach ($products as $product) {
                if ($sysProduct['data_id'] == $product['id']) {
                    $price += $sysProduct[$field] * $product['num'] * 100;
                }
            }
        }
        return $price;
    }

    public function jssdk(Request $request)
    {
        try {

            $url = $request->input('url');
            if ($url === null) throw new \Exception('参数错误');

            $app = Factory::officialAccount(config('wechat.official_account.default'));
            // 创建缓存实例
            $cache = new RedisAdapter(app('redis')->connection()->client());
            // 替换应用中的缓存
            $app->rebind('cache', $cache);
            $app->jssdk->setUrl($url);
            return $this->success($app->jssdk->buildConfig(['chooseWXPay', 'closeWindow', 'scanQRCode'], true, false, false));

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function wechatPay(Request $request)
    {
        try {

            if ($request->input('order_id') === null || $request->input('patient_id') === null) throw new Exception('参数错误');

            $app = Factory::payment(config('wechat.payment.default'));
            // 创建缓存实例
            $cache = new RedisAdapter(app('redis')->connection()->client());
            // 替换应用中的缓存
            $app->rebind('cache', $cache);

            // TODO 获取订单信息
            $order = OrderModel::find($request->input('order_id'));
            if ($order === null) throw new \Exception('异常订单');

            // TODO 获取患者信息
            $patient = PatientModel::find($request->input('patient_id'));
            if ($patient === null) throw new \Exception('患者信息异常');

            $result = $app->order->unify([
                'body' => $order->order_info_title,
                'out_trade_no' => $order->order_info_no,
                'total_fee' => env('WECHAT_PAYMENT_SANDBOX', false) ? 101 : $order->order_info_payment,
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $patient->wx_oa_openid
            ]);

            \Log::debug(json_encode($result));
            if ($result['return_code'] == 'FAIL') throw new \Exception($result['return_msg']);

            $data = $app->jssdk->sdkConfig($result['prepay_id']);
            if ($result['return_code'] == 'SUCCESS') {
                return $this->success($data);
            } else {
                throw new \Exception($result['return_msg']);
            }

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getOrderStatus(Request $request)
    {
        try {

            $orderId = $request->input('order_id');
            if ($orderId == null) throw new \Exception('参数错误');
            $order = OrderModel::has('products')->find($orderId);
            if ($order === null) throw new \Exception('数据异常');

            $data = ['is_pay' => $order->order_info_paystatus];
            // 如果是已付款
            if ($order->order_info_paystatus) {
                $data['product_category'] = $order->products ? $order->products[0]->product_category : 3;
                $data['product_name'] = $order->products ? $order->products[0]->product_name : $order->order_info_title;
                $data['qrcode'] = $order->order_info_qrcode;
                $data['delivery_type'] = $order->order_info_delivery_type;
                $data['delivery_type_text'] = $order->order_info_delivery_type_text;
            }

            return $this->success($data);
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    private function createQrcode($orderId)
    {
        try {
            $app = Factory::officialAccount(config('wechat.official_account.default'));
            // 创建缓存实例
            $cache = new RedisAdapter(app('redis')->connection()->client());
            // 替换应用中的缓存
            $app->rebind('cache', $cache);
            $data = json_encode(['qrCodeType' => 4, 'others' => $orderId]);
            $result = $app->qrcode->forever($data);
            Log::channel('wechat_pay')->debug($result);
            if (isset($result['errcode'])) throw new \Exception($result['errmsg']);
            Log::channel('wechat_pay')->info($result);
            return $result;
        } catch (\Exception $e) {
            return ['error' => true, 'msg' => $e->getMessage()];
        }
    }

    public function test()
    {
        $orderInfo = OrderModel::with(['products', 'address'])->where('order_info_no', '=', '220915112632586490')->first();
        var_dump($orderInfo);
    }


    public function payCallback()
    {

        $payApp = Factory::payment(config('wechat.payment.default'));
        // 创建缓存实例
        $cache = new RedisAdapter(app('redis')->connection()->client());
        // 替换应用中的缓存
        $payApp->rebind('cache', $cache);


        $qyApp = \EasyWeChat\Factory::work(config('wechat.work.default'));
        // 创建缓存实例
        $cache = new RedisAdapter(app('redis')->connection()->client());
        // 替换应用中的缓存
        $qyApp->rebind('cache', $cache);


        $response = $payApp->handlePaidNotify(function ($message, $fail) use ($qyApp) {
            Log::channel('wechat_pay')->debug($message);
            Log::channel('wechat_pay')->info($message['out_trade_no']);
            try {
                // 根据返回的订单号查询订单数据
                $orderInfo = OrderModel::with(['products', 'address'])->where('order_info_no', '=', $message['out_trade_no'])->first();
                if ($orderInfo == null) throw new \Exception('订单不存在');

                // 已支付
                if ($orderInfo->order_info_paystatus == 1) return true;
                // 已支付、已完成
                if (in_array($orderInfo->order_info_orderstatus, [3, 4])) return true;

                if($message['result_code'] === 'SUCCESS') {
                    $orderInfo->order_info_paystatus = 1;
                    $orderInfo->order_info_orderstatus = 3;
                    $orderInfo->transaction_id = $message['transaction_id'];
                    // 2 为试纸，不需要生成二维码 (废弃) 改为所有商品都需要生成二维码
                    // if ($orderInfo->products != null && $orderInfo->products[0]['product_category'] != 2) {
                        $qrcode = $this->createQrcode($orderInfo->data_id);
                        if (isset($qrcode['error'])) {
                            Log::channel('wechat_pay')->error($qrcode['msg']);
                            throw new \Exception('二维码创建失败');
                        }
                        $orderInfo->order_info_qrcode = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='.urlencode($qrcode['ticket']);
                        $orderInfo->order_info_qrcode_result = $qrcode['url'];
                    // }
                    $save = $orderInfo->save();
                    if (!$save) throw new \Exception('数据处理失败');
                }

                $groupKey = 'af5ea5ff-474f-4e0c-ac9f-3847d2d4e49c';
                $messenger = $qyApp->group_robot_messenger;
                $payment = $orderInfo->order_info_payment/100;
                // $nums = array_sum(Arr::pluck($orderInfo->products, 'product_num'));
                $products = [];
                foreach ($orderInfo->products as $product) {
                    $products[] = $product->product_name . '*' . $product->product_num;
                }
                $productsStr = implode('、', $products);
                $content = "## <font color=\"warning\">有新的商城订单！</font>
                    > 购买商品：{$productsStr}
                    > 购买金额：{$payment}
                    > 订单号：{$orderInfo->order_info_no}
                    > 收货人：{$orderInfo->address->contact_person}
                    > 收货电话：{$orderInfo->address->contact_phone}
                    > 收货地址：{$orderInfo->address->contact_address}
                ";

                $markdown = new Markdown($content);
                $messenger->message($markdown)->toGroup($groupKey)->send();

                return true;

            } catch (\Exception $e) {
                Log::channel('wechat_pay')->error($e->getMessage());
                return $fail($e->getMessage());
            }
        });
        return $response;
    }

    public function getAddress(Request $request)
    {
        try {

            if($request->input('patient_id') === null) throw new \Exception('参数错误');

            $data = PatientAddressModel::where('patient_id', $request->input('patient_id'))
                ->where('is_del', 0)
                ->orderBy('create_time', 'desc')
                ->get();

            return $this->success($data);
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function editPatientAddress(AddressRequest $request)
    {
        try {

            $status = PatientAddressModel::updateOrCreate(['data_id' => $request->input('data_id')], [
                'patient_id' => $request->input('patient_id'),
                'contact_person' => $request->input('contact_person'),
                'contact_phone' => $request->input('contact_phone'),
                'contact_province_id' => $request->input('contact_province_id'),
                'contact_province_name' => $request->input('contact_province_name'),
                'contact_city_id' => $request->input('contact_city_id'),
                'contact_city_name' => $request->input('contact_city_name'),
                'contact_district_id' => $request->input('contact_district_id'),
                'contact_district_name' => $request->input('contact_district_name'),
                'contact_address' => $request->input('contact_address'),
                'is_default' => $request->input('is_default', 0),
            ]);

            return $status ? $this->success() : $this->error('操作失败');
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function deletePatientAddress(Request $request)
    {
        try {

            if($request->input('data_id') === null) throw new \Exception('参数错误');

            $data = PatientAddressModel::find($request->input('data_id'));
            $data->is_del = 1;
            $status = $data->save();

            return $status ? $this->success() : $this->error('操作失败');
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function addToCart(Request $request)
    {

        try {

            $productId = $request->input('product_id');
            $num = $request->input('num', 1);
            $patientId = $request->input('patient_id');
            if ($productId == null) throw new \Exception('商品信息异常');

            $patient = PatientModel::with('relation.doctor')->find($patientId);
            $orgCode = $patient->relation->doctor->org_code ?? null;
            if ($orgCode == null) {
                $orgCode = 'A01A02';
                // throw new \Exception('数据异常！');
            }
            if ($patient == null) throw new \Exception('数据异常');

            $add = CartModel::create([
                'patient_id' => $patientId,
                'product_id' => $productId,
                'num' => $num,
                'org_code' => $orgCode
            ]);

            return $add ? $this->success() : $this->error('购物车添加失败');

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function editCart(Request $request)
    {
        try {

            $cartId = $request->input('cart_id');
            $num = $request->input('num', 1);
            if (empty($cartId)) throw new \Exception('参数错误');

            $cart = CartModel::find($cartId);
            if ($cart == null) throw new \Exception('数据异常');

            $cart->num = $num;
            $update = $cart->save();

            return $update ? $this->success() : $this->error('操作失败');

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function deleteCart(Request $request)
    {
        try {

            $cartId = $request->input('cart_id');
            if (empty($cartId)) throw new \Exception('参数错误');

            $cartIdArr = explode(',', $cartId);
            foreach ($cartIdArr as $item) {
                $cart = CartModel::find($item);
                if ($cart == null) continue;
                $cart->is_del = 1;
                $cart->save();
            }

            return $this->success();

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getCart(Request $request)
    {
        try {

            $patientId = $request->input('patient_id');

            $patient = PatientModel::with('relation.doctor')->find($patientId);
            $orgCode = $patient->relation->doctor->org_code ?? null;
            if ($orgCode == null) {
                $orgCode = 'A01A02';
                // throw new \Exception('数据异常！');
            }
            if ($patient == null) throw new \Exception('数据异常');

            $data = CartModel::with('product')->where('is_del', 0)->where('patient_id', $patientId)->where('org_code', $orgCode)->get();
            return $this->success(CartResource::collection($data));

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function confirmOrder(Request $request)
    {
        try {

            $products = $request->input('products');
            $usePrice = $request->input('use_price', 'product_price');
            if (!is_array($products)) throw new \Exception('参数错误');

            $productIds = Arr::pluck($products, 'id');

            $sysProducts = ProductModel::whereIn('data_id', $productIds)->get();

            $totalPrice = 0;
            foreach ($sysProducts as &$product) {
                foreach ($products as $item) {
                    if ($product->data_id == $item['id']) {
                        $product['num'] = $item['num'];
                    }
                }
                $price = empty($product[$usePrice]) ? $product['product_price'] : $product[$usePrice];
                $totalPrice += $price * $product['num'];
            }

            $result = [
                'list' => ProductResource::collection($sysProducts),
                'total_price' => $totalPrice
            ];
            return $this->success($result);

        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function qrcode(Request $request)
    {
        try {

            $id = $request->input('id');
            if (is_null($id)) throw new \Exception('参数错误');

            $push = PushModel::find($id);
            if (is_null($push)) throw new \Exception('数据异常');
            return $this->success(new PushResource($push));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getOrderList(Request $request)
    {
        try {
            $patientId = $request->input('patient_id');
            if (empty($patientId)) throw new \Exception('参数错误');

            $orders = OrderModel::with(['products','address'])->where('order_info_orderstatus', '<>', 2)->where('order_info_userid', $patientId)->orderBy('create_time', 'desc')->get();
            return $this->success(OrderResource::collection($orders));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }

    public function getOrderDetail(Request $request)
    {
        try {
            $orderId = $request->input('order_id');
            if (empty($orderId)) throw new \Exception('参数错误');

            $orders = OrderModel::with(['products','address'])->find($orderId);
            return $this->success(new OrderResource($orders));
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }
}
